import datetime
import json
import re
import random

from django.db import transaction
from django.db.models import Q
import time
from django.shortcuts import render
from rest_framework_simplejwt.tokens import RefreshToken
from django.contrib.auth import authenticate
from django_redis import get_redis_connection
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination
from rest_framework.generics import ListAPIView
from rest_framework.permissions import IsAuthenticated
from django.core.cache import cache
from utils.sendsms import Sendcode
from home import models, ser
# Create your views here.
from courses import models, ser
from utils.snowflake import SnowflakeSingleton
from superuser.models import SuperUser

class LoginByPwd(APIView):
    def post(self, request):
        username = request.data.get('username')
        password = request.data.get('password')
        if not all([username, password]):
            return Response({
                'code': 400,
                'msg': '参数不全'
            })
        user = authenticate(username=username, password=password)
        if not user:
            return Response({
                'code': 400,
                'msg': '用户名或密码错误'
            })
        refresh = RefreshToken.for_user(user)
        return Response({
            'code': 200,
            'msg': '登录成功',
            'data': {
                'token': str(refresh.access_token),
                'refresh': str(refresh),
                'username': user.username,
                'id': user.id,
            }
        })


class Send(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        if not phone:
            return Response({
                'code': 400,
                'msg': '手机号不能为空'
            })
        result = re.match(r'^1[3-9]\d{9}$', phone)
        if not result:
            return Response({
                'code': 400,
                'msg': '手机号格式错误'
            })
        key = 'user:send:code' + phone
        cachecode = cache.get(key)
        if cachecode:
            return Response({
                'code': 200,
                'msg': '请勿频繁发送验证码'
            })
        code = str(random.randint(1000, 9999))
        Sendcode.send_message(phone, code)
        cache.set(key, code, 60)
        return Response({
            'code': 200,
            'msg': '发送成功'
        })


class Login(APIView):
    def post(self, request):
        phone = request.data.get('phone')
        code = request.data.get('code')
        if not all([phone, code]):
            return Response({
                'code': 400,
                'msg': '参数不全'
            })
        result = re.match(r'^1[3-9]\d{9}$', phone)
        if not result:
            return Response({
                'code': 400,
                'msg': '手机号格式错误'
            })
        key = 'user:send:code' + phone
        cachecode = cache.get(key)
        if cachecode != code:
            return Response({
                'code': 400,
                'msg': '验证码错误'
            })
        userinfo = SuperUser.objects.filter(phone=phone).first()
        if not userinfo:
            userinfo = SuperUser.objects.create(phone=phone, username=phone)
        refresh = RefreshToken.for_user(userinfo)
        return Response({
            'code': 200,
            'msg': '登录成功',
            'data': {
                'token': str(refresh.access_token),
                'refresh': str(refresh),
                'username': userinfo.username,
                'id': userinfo.id,
            }
        })



class Nav(APIView):
    def get(self, request):
        key = 'home:nav:list'
        navList = cache.get(key)
        if navList:
            return Response({
                'code': 200,
                'msg': '请求成功',
                'data': navList
            })
        navlist = models.Nav.objects.filter(is_del=False, is_show=True).order_by('sort')
        res = ser.NavSerializer(navlist, many=True)
        if not res.data:
            cache.set(key, [], 60 * 60 * 24)
        cache.set(key, res.data, 60 * 60 * 24)
        return Response({
            'code': 200,
            'msg': '请求成功',
            'data': res.data
        })


class Category(APIView):
    def get(self, request):
        key = 'home:category:list'
        categoryList = cache.get(key)
        if categoryList:
            return Response({
                'code': 200,
                'msg': '请求成功',
                'data': categoryList
            })
        categorylist = models.Category.objects.filter(is_del=False, is_show=True, parent=None).order_by('sort')
        res = ser.CategorySerializer(categorylist, many=True)
        if not res.data:
            cache.set(key, [], 60 * 60 * 24)
        cache.set(key, res.data, 60 * 60 * 24)
        return Response({
            'code': 200,
            'msg': '请求成功',
            'data': res.data
        })


class Banner(APIView):
    def get(self, request):
        kay = 'home:banner:list'
        bannerList = cache.get(kay)
        if bannerList:
            return Response({
                'code': 200,
                'msg': '请求成功',
                'data': bannerList
            })
        bannerlist = models.Banner.objects.filter(is_del=False, is_show=True).order_by('sort')
        res = ser.BannerSerializer(bannerlist, many=True)
        if not res.data:
            cache.set(kay, [], 60 * 60 * 24)
        cache.set(kay, res.data, 60 * 60 * 24)
        return Response({
            'code': 200,
            'msg': '请求成功',
            'data': res.data
        })


class MyPagination(PageNumberPagination):
    page_size = 10
    page_size_query_param = 'size'


class CourseList(ListAPIView):
    queryset = models.Course.objects.all()
    serializer_class = ser.CourseSerializer
    pagination_class = MyPagination

    def get_queryset(self):
        query = Q(status=1)
        nav_name = self.request.query_params.get('nav_name')
        cate = self.request.query_params.get('cate')
        price_range = self.request.query_params.get('price_range')
        sort = self.request.query_params.get('sort')
        keyword = self.request.query_params.get('keyword')
        if nav_name:
            query &= Q(nav_relations__nav_category__name=nav_name)
        if cate:
            query &= Q(categories__id=cate)
        if price_range:
            query &= Q(course_type=price_range)
        if sort:
            return self.queryset.filter(query).select_related('teacher').order_by("-"+sort)
        if keyword:
            query &= (Q(name__icontains=keyword) | Q(description__icontains=keyword) | Q(brief__icontains=keyword) |
                      Q(teacher__name__icontains=keyword))
        return self.queryset.filter(query).select_related('teacher')


class CourseDetail(APIView):
    def get(self, request):
        pk = request.query_params.get('id')
        if not pk:
            return Response({
                'code': 400,
                'msg': '参数不全'
            })
        info = models.Course.objects.filter(id=pk, is_show=True, is_del=False).first()
        if not info:
            return Response({
                'code': 400,
                'msg': '课程不存在'
            })
        res = ser.CourseDetailSerializer(info)
        # chapters = models.CourseChapter.objects.filter(course_id=id)
        # res = ser.CourseDetailSerializer(chapters, many=True)
        # data = res.data
        # for item in data:
        #     lessons = models.CourseLesson.objects.filter(chapter_id=item['id'])
        #     lessons_ser = ser.CourseLessonSerializer(lessons, many=True)
        #     item['lessons'] = lessons_ser.data
        return Response({
            'code': 200,
            'msg': 'ok',
            'data': res.data
        })


class AddCart(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        user = request.user
        course_id = request.data.get('course_id')
        if not course_id:
            return Response({
                'code': 400,
                'msg': '参数不全'
            })
        info = models.Course.objects.filter(id=course_id, is_show=True, is_del=False, status=1).first()
        if not info:
            return Response({
                'code': 400,
                'msg': '课程不存在'
            })
        conn = get_redis_connection('cart')
        cart_key = 'majing:cart:cart_list:' + str(user)
        course_key = 'course:' + str(course_id)
        if conn.hexists(cart_key, course_key):
            return Response({
                'code': 400,
                'msg': '购物车中已存在此课程'
            })
        course_info = {
            'course_id': course_id,
            'price': float(info.price),
            'course_name': info.name,
            'course_img': str(info.course_img),
            'selected': 1,
            'add_time': int(time.time()),
            'validity': "永久有效期",
        }
        conn.hset(cart_key, course_key, json.dumps(course_info))
        return Response({
            'code': 200,
            'msg': '添加成功'
        })



from majing import models, ser
class CartList(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        cart_key = 'majing:cart:cart_list:' + str(user.id)
        conn = get_redis_connection('cart')
        cart_info = conn.hgetall(cart_key)
        if not cart_info:
            return Response({"msg": "购物车为空", "code": 400})
        cart_list = []
        for course_id, course_info in cart_info.items():
            course_info = json.loads(course_info.decode('utf-8'))
            expire = models.CourseExplain.objects.filter(course_id=course_info['course_id'])
            if expire:
                expire_data = ser.CartSerializer(expire, many=True)
                course_info['expire'] = expire_data.data
            else:
                course_info['expire'] = [{'expire_time': 0, 'expire_text': '永久有效', 'price': course_info['price']}]
            cart_list.append(course_info)
        cart_list = sorted(cart_list, key=lambda x: x['add_time'], reverse=True)
        return Response({
            'code': 200,
            'msg': '请求成功',
            'data': cart_list
        })



class CartUpdate(APIView):
    def put(self, request):
        user = request.user
        course_id = request.data.get('course')
        if not course_id:
            return Response({
                'code': 400,
                'msg': '参数不全'
            })
        cart_key = 'majing:cart:cart_list:' + str(user.id)
        course_key = 'course:' + str(course_id)
        conn = get_redis_connection('cart')
        if not conn.hexists(cart_key, course_key):
            return Response({
                'code': 400,
                'msg': '购物车中没有此课程'
            })
        course_info = conn.hget(cart_key, course_key)
        course = json.loads(course_info.decode('utf-8'))
        course['selected'] = not course['selected']
        conn.hset(cart_key, course_key, json.dumps(course))
        return Response({
            'code': 200,
            'msg': '修改成功',
        })


class CartDelete(APIView):
    def post(self, request):
        user = request.user
        course_id = request.data.get('course_ids')
        if not course_id:
            return Response({
                'code': 400,
                'msg': '参数不全'
            })
        cart_key = 'majing:cart:cart_list:' + str(user.id)
        course_key = 'course:' + str(course_id)
        conn = get_redis_connection('cart')
        if not conn.hexists(cart_key, course_key):
            return Response({
                'code': 400,
                'msg': '购物车中没有此课程'
            })
        try:
            conn.hdel(cart_key, course_key)
            return Response({
                'code': 200,
                'msg': '删除成功'
            })
        except:
            return Response("删除失败")


class CartMany(APIView):
    def post(self, request):
        user = request.user
        ids = request.data.get('ids')
        if not ids:
            return Response({
                'code': 400,
                'msg': '参数不全'
            })
        cart_key = 'majing:cart:cart_list:' + str(user.id)
        conn = get_redis_connection('cart')
        cart_info = conn.hgetall(cart_key)
        try:
            for course_id in list(ids):
                course_key = 'course:' + str(course_id)
                conn.hdel(cart_key, course_key)
            return Response({"msg": "删除成功", "code": 200})
        except:
            return Response({"msg": "删除失败", "code": 400})


class CartExpire(APIView):
    def put(self, request):
        user = request.user
        course_id = request.data.get('course')
        expire = request.data.get('expire')
        expireprice = request.data.get('expireprice')
        if not course_id:
            return Response({
                'code': 400,
                'msg': '参数不全'
            })
        cart_key = 'majing:cart:cart_list:' + str(user.id)
        course_key = 'course:' + str(course_id)
        conn = get_redis_connection('cart')
        if not conn.hexists(cart_key, course_key):
            return Response({
                'code': 400,
                'msg': '购物车中没有此课程'
            })
        course_info = conn.hget(cart_key, course_key)
        course = json.loads(course_info.decode('utf-8'))
        course['validity'] = expire
        course['price'] = expireprice
        conn.hset(cart_key, course_key, json.dumps(course))
        return Response({
            'code': 200,
            'msg': '修改成功'
        })



class Select(APIView):
    permission_classes = [IsAuthenticated]

    def get(self, request):
        user = request.user
        conn = get_redis_connection('cart')
        cart_key = 'majing:cart:cart_list:' + str(user.id)
        cart_info = conn.hgetall(cart_key)
        cart_list = []
        for key, val in cart_info.items():
            course_info = json.loads(val.decode('utf-8'))
            if course_info['selected']:
                cart_list.append(course_info)
        if not cart_list:
            return Response({'code': 400, 'msg': '购物车中没有选中的产品'})
        return Response({'code': 200, 'msg': 'ok', 'data': cart_list})


class Create(APIView):
    permission_classes = [IsAuthenticated]

    @transaction.atomic
    def post(self, request):
        try:
            user = request.user
            pay_type = request.data.get('pay_type')
            desc = request.data.get('desc', '')
            flake = SnowflakeSingleton.get_instance(worker_id=2)
            order_info = {
                'user': user.id,
                'order_number': flake.get_id(),
                'pay_type': pay_type,
            }
            total = 0
            conn = get_redis_connection('cart')
            cart_key = 'majing:cart:cart_list:' + str(user.id)
            cart_info = conn.hgetall(cart_key)
            cart_list = []
            for key, val in cart_info.items():
                course_info = json.loads(val.decode('utf-8'))
                if course_info['selected']:
                    cart_list.append(course_info)
                    total += float(course_info['price'])
            order_info['pay_price'] = total
            order_info['total'] = total
            order_info['order_desc'] = desc
            res = orderser.OrderSerializer(data=order_info)
            if not res.is_valid():
                return Response({'code': 400, 'msg': res.errors})
            res.save()
            # 添加分布式锁
            lock_key = 'order:lock:' + res.data['order_number']
            res_lock = conn.setnx(lock_key, 1)
            if not res_lock:
                return Response({'code': 400, 'msg': '请勿重复提交订单'})
            for item in cart_list:
                detail_info = {
                    'order': res.data['id'],
                    'order_number': res.data['order_number'],
                    'course': item['course_id'],
                    'price': item['price'],
                    'expire_text': item['validity'],
                }
                if item['validity'] == '永久有效期':
                    detail_info['expire_time'] = datetime.datetime.now() + datetime.timedelta(weeks=100)
                    detail_info['expire_day'] = 0
                if item['validity'] == '30天有效期':
                    detail_info['expire_time'] = datetime.datetime.now() + datetime.timedelta(days=30)
                    detail_info['expire_day'] = 30
                detail_ser = orderser.OrderDetailSerializer(data=detail_info)
                if not detail_ser.is_valid():
                    return Response({'code': 400, 'msg': detail_ser.errors})
                detail_ser.save()
            for key, val in cart_info.items():
                course = json.loads(val.decode('utf-8'))
                if course['selected']:
                    course_key = 'course:' + str(course['course_id'])
                    conn.hdel(cart_key, course_key)
            conn.delete(lock_key)
            return Response({'code': 200, 'msg': '生成订单成功', 'data': res.data})
        except Exception as e:
            return Response({'code': 500, 'msg': '生成订单失败', "error": str(e)})


from order import orderser
